26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
52 #pragma package(smart_init)
62 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
63 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
64 int IncrementalDigitsIn,
int SignallerMaxSpeedIn): RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
65 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
66 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
67 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
78 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
79 AnsiString(TrainModeIn));
123 for(
int x = 0; x < 4; x++)
132 for(
int x = 0; x < 4; x++)
141 for(
int x = 0; x < 4; x++)
146 for(
int x = 0; x < 4; x++)
150 for(
int x = 0; x < 3; x++)
187 for(
int x = 0; x < 4; x++)
232 throw Exception(
"Error in attempting to delete FrontCodePtr");
236 for(
int x = 0; x < 4; x++)
240 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
245 for(
int x = 0; x < 4; x++)
249 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
278 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
340 bool TempDerail =
false;
384 else if((NextElementPosition > -1) && (NextEntryPos > -1))
450 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
461 for(
int x = 0; x < 4; x++)
468 for(
int x = 0; x < 4; x++)
700 if((random(RandRange)) == 0)
715 int LockedVectorNumber;
928 if(BufferLocation ==
"")
931 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
995 int NextElementPosition, NextEntryPos;
1019 NextElementPosition = -1;
1023 if((NextElementPosition > -1) && (NextEntryPos > -1))
1139 AnsiString StationName;
1150 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1164 if((NextElementPosition > -1) && (NextEntryPos > -1))
1291 if(NextElementPosition > -1)
1330 AnsiString Loc =
"";
1331 bool LocNamed =
false;
1360 Loc =
"outside railway";
1386 NextElementPosition = -1;
1399 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1418 if((NextElementPosition > -1) && (NextEntryPos > -1))
1457 FirstPair.second).
GetELink() == TempELink))
1462 SecondPair.second).
GetELink() == TempELink))
1477 FirstPair.second).
GetELink() == TempELink))
1482 SecondPair.second).
GetELink() == TempELink))
1497 FirstPair.second).
GetELink() == TempELink))
1502 SecondPair.second).
GetELink() == TempELink))
1535 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1538 int NewLastElement = 0, NewLastExitPos = 0;
1552 if(NewLastElement == -1)
1555 throw Exception(
"Error, Connection = -1 in Continuation loop in UpdateTrain");
1558 if(NewLastExitPos == -1)
1560 throw Exception(
"Error, ConnLinkPos = -1 in Continuation loop in UpdateTrain");
1562 LastElement = NewLastElement;
1563 LastExitPos = NewLastExitPos;
1566 if(CumDistance < 1200)
1572 int FirstDistance = 0;
1573 if(CumDistance >= 1200)
1574 FirstDistance = 100;
1576 FirstDistance = 1200 - CumDistance;
1577 if(FirstDistance < 100)
1578 FirstDistance = 100;
1603 if(VectorIT->RouteNumber == RouteNumber)
1648 LockedVectorNumber)))
1809 for(
int x = 0; x < 4; x++)
1816 for(
int x = 0; x < 4; x++)
1843 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
1848 if(OtherTrainEntryPos == -1)
1850 throw Exception(
"Error - OtherTrainEntryPos not set");
1869 int OtherTrainID = -1;
1870 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
1965 bool StopRequired =
false;
1978 int NextElementEntryPos = -1;
1979 int NextElementExitPos = -1;
1980 bool TrainOnNextElement =
false;
1981 bool StopSignalAtNextElement =
false;
1982 if(ForwardConnection)
1990 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
1993 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2049 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2263 if(Code.Length() != 4)
2265 for(
int x = 1; x < 5; x++)
2272 for(
int x = 0; x < 4; x++)
2420 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2432 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2443 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2452 TRect SourceRect, DestRect;
2454 DestRect.init(0, 0, 8, 8);
2457 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2459 TempGraphic->PixelFormat = pf8bit;
2460 TempGraphic->Width = 16;
2461 TempGraphic->Height = 16;
2467 TempGraphic->Transparent =
true;
2471 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2472 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2476 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2482 else if(TempElement.
SpeedTag == 89)
2484 else if(TempElement.
SpeedTag == 90)
2486 else if(TempElement.
SpeedTag == 91)
2488 else if(TempElement.
SpeedTag == 92)
2490 else if(TempElement.
SpeedTag == 93)
2492 else if(TempElement.
SpeedTag == 94)
2494 else if(TempElement.
SpeedTag == 95)
2496 TempGraphic->Transparent =
true;
2500 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2501 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2503 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2510 for(
int x = 0; x < 40; x++)
2525 TempGraphic->Transparent =
true;
2529 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2530 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2532 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2546 TempGraphic->Transparent =
true;
2550 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2551 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2554 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2556 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2561 TempGraphic->Transparent =
true;
2565 int BDVectorPos = -1;
2574 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2579 TempGraphic->Transparent =
true;
2583 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2584 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2586 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2592 TempGraphic->Transparent =
true;
2596 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2597 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2599 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2865 throw Exception(
"Error, same train on two different bridge tracks");
2911 AnsiString(EntryPos) +
"," +
HeadCode);
2929 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
2944 AnsiString(EntryPos) +
"," +
HeadCode);
2953 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
2980 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
2981 int LockedVectorNumber;
2993 TRect SourceRect, DestRect;
2994 DestRect.init(0, 0, 8, 8);
3001 int FirstELink, SecondELink = -1;
3004 if(RoutePair2.first > -1)
3011 if(SecondELink == -1)
3013 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3018 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3028 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3029 DestGraphic->PixelFormat = pf8bit;
3030 DestGraphic->Width = 8;
3031 DestGraphic->Height = 8;
3032 DestGraphic->Transparent =
true;
3035 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3044 PrefDirElement, LockedVectorNumber))
3059 if(ElementEntryPos > 1)
3081 AnsiString(EntryPos) +
"," +
HeadCode);
3083 bool WrongRoute =
false;
3108 int LinkNumber = TrackElement.
Link[EntryPos];
3109 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3114 bool LogActionErrorCalled =
false;
3123 LogActionErrorCalled =
true;
3139 else if(LinkNumber == 3)
3146 LogActionErrorCalled =
true;
3162 else if(LinkNumber == 7)
3169 LogActionErrorCalled =
true;
3185 else if(LinkNumber == 9)
3192 LogActionErrorCalled =
true;
3223 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3228 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3238 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3243 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3252 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3270 bool ColourError =
false, ColourError2 =
false;
3274 ColourError2 =
true;
3275 for(
int x = 0; x < 4; x++)
3279 ColourError2 =
true;
3284 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3289 for(
int x = 0; x < 4; x++)
3376 AnsiString(EntryPos) +
"," +
HeadCode);
3377 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3378 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3379 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3380 TrainInFrontInSignallerModeFlag =
false;
3381 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3382 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3383 bool SignallerStopRequired =
false;
3394 if(CurrentTrackVectorPosition > -1)
3398 if((EntryPos == 0) || (EntryPos == 2))
3411 else if(EntryPos == 1)
3435 EntryHalfLength = CurrentElementHalfLength;
3440 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3444 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3490 FrontElementMaxSpeed = LimitingSpeed;
3521 double ExitSpeedAtMaxBraking;
3526 ExitSpeedAtMaxBraking = 0;
3536 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3538 SpeedToUse = ExitSpeedAtMaxBraking;
3542 SpeedToUse = LimitingSpeed;
3557 RedSignalFlag =
false;
3558 BuffersFlag =
false;
3559 StationFlag =
false;
3560 BuffersOrContinuationNowFlag =
false;
3561 ContinuationNextFlag =
false;
3564 CumulativeLength += (2 * CurrentElementHalfLength);
3567 SignallerStopRequired =
true;
3589 bool StopRequired =
false;
3603 StationFlag =
false;
3610 BuffersOrContinuationNowFlag =
true;
3612 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
3616 if((EntryPos == 0) || (EntryPos == 2))
3630 if(NextTrackVectorPosition > -1)
3635 if((NextEntryPos == 0) || (NextEntryPos == 2))
3648 else if(NextEntryPos == 1)
3661 if(NextEntryPos > 1)
3675 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
3686 RedSignalFlag =
true;
3705 TrainInFrontInSignallerModeFlag =
true;
3729 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
3741 double MaxHalfSpeed;
3745 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
3746 MaxHalfSpeed = FrontElementMaxSpeed;
3748 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
3755 bool HalfSpeedLimited =
false;
3759 HalfSpeedLimited =
true;
3784 if(HalfSpeedLimited)
3805 if(SignallerStopRequired)
3821 int TempMaxExitSpeed;
3824 if(MaxExitSpeedAtHalfBrakingSquared < 10)
3825 MaxExitSpeedAtHalfBraking = 0;
3827 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
3830 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
3831 TempMaxExitSpeed = FrontElementMaxSpeed;
3833 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
3843 if(ExitSpeedHalfSquared < 10)
3849 if(ExitSpeedFullSquared < 10)
3913 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
3914 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
3934 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
3935 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
3945 if(!BuffersOrContinuationNowFlag)
3947 if(NextSpeedLimit < LimitingSpeed)
3948 LimitingSpeed = NextSpeedLimit;
3951 int TempMaxExitSpeed;
3955 if(MaxExitSpeedAtHalfBrakingSquared < 10)
3956 MaxExitSpeedAtHalfBraking = 0;
3958 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
3959 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
3960 TempMaxExitSpeed = FrontElementMaxSpeed;
3962 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
3970 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
3979 if(!BuffersOrContinuationNowFlag)
3981 CurrentTrackVectorPosition = NextTrackVectorPosition;
3982 EntryPos = NextEntryPos;
3983 CurrentElementHalfLength = NextElementHalfLength;
3986 ContinuationNextFlag =
true;
3990 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4010 if(ExitSpeedHalfSquared < 10)
4016 if(ExitSpeedFullSquared < 10)
4070 double DeltaExitTimeToMaxInSecs;
4071 double DistanceToMax;
4080 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4082 DistanceToMax = EntryHalfLength;
4085 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4086 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4099 double DeltaExitTimeToMaxInSecs;
4100 double DistanceToMax;
4109 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4111 DistanceToMax = EntryHalfLength / 2;
4114 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4115 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4126 if(ExitSpeedHalfSquared < 10)
4132 if(ExitSpeedFullSquared < 10)
4147 if((EntryPos == 0) || (EntryPos == 2))
4161 if(NextTrackVectorPosition > -1)
4163 int NextElementLength;
4164 if(NextEntryPos > 1)
4172 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4308 if((Ptr->Command ==
"cdt") || (Ptr->FormatType ==
Repeat))
4312 if((Ptr->ArrivalTime > TDateTime(-1)) && (Ptr->LocationName == Name))
4321 if((Ptr->EventTime > TDateTime(-1)) && (Ptr->LocationName == Name) && (Ptr->Command ==
"pas"))
4346 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4364 CurrentTrackVectorPosition).
Attribute != 4))
4400 if((EntryPos == 0) || (EntryPos == 2))
4414 CurrentTrackVectorPosition = NextTrackVectorPosition;
4415 EntryPos = NextEntryPos;
4439 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4463 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4464 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4465 int RouteStartPosition;
4467 int PlatformPosition;
4469 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
4508 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
4511 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
4557 if(!PlatformFoundFlag)
4558 PlatformPosition = CurrentTrackVectorPosition;
4560 PlatformFoundFlag =
true;
4576 if((EntryPos == 0) || (EntryPos == 2))
4611 if(ElementNumber < 2)
4612 SkipRouteCheck =
true;
4614 SkipRouteCheck =
false;
4615 if(ElementNumber == 1)
4617 RouteStartPosition = CurrentTrackVectorPosition;
4627 if(ElementNumber > 1)
4630 RouteOrPartRouteSet =
true;
4632 RouteOrPartRouteSet =
false;
4634 if(!SkipRouteCheck && !RouteOrPartRouteSet)
4641 int ExitLink = CurrentTrackElement.
Link[ExitPos];
4642 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
4654 Distance += CurrentTrackElement.
Length01;
4656 Distance += CurrentTrackElement.
Length23;
4657 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
4658 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
4659 CurrentTrackVectorPosition = NextTrackVectorPosition;
4660 EntryPos = NextEntryPos;
4697 return RepeatHeadCode;
4718 bool FrontValid =
false, RearValid =
false;
4719 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
4723 TrainToBeJoinedBy = NULL;
4737 int TrainToBeJoinedByID = -1;
4758 if((TrainToBeJoinedByID < 0) && RearValid)
4777 if(TrainToBeJoinedByID < 0)
4779 TrainToBeJoinedBy = NULL;
4784 if(!TrainToBeJoinedBy->
Stopped())
4786 TrainToBeJoinedBy = NULL;
4797 TDateTime TimetableNonRepeatTime,
bool Warning)
4832 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
4833 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
4834 int IntMinsLate = 0;
4838 ActionLog =
" arrived at ";
4846 ActionLog =
" terminated at ";
4850 ActionLog =
" departed from ";
4851 if(ActionType ==
Pass)
4852 ActionLog =
" passed ";
4854 ActionLog =
" created at ";
4855 if(ActionType ==
Enter)
4856 ActionLog =
" entered railway at ";
4857 if(ActionType ==
Leave)
4858 ActionLog =
" left railway at ";
4860 ActionLog =
" split from front to ";
4862 ActionLog =
" split from rear to ";
4864 ActionLog =
" joined by ";
4866 ActionLog =
" changed direction at ";
4868 ActionLog =
" became new service ";
4870 ActionLog =
" taken under signaller control at ";
4872 ActionLog =
" restored to timetable control at ";
4876 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
4878 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
4880 ActionLog =
" REMOVED FROM RAILWAY at ";
4883 ActionLog =
" received signaller authority to proceed";
4885 ActionLog =
" received signaller authority to step forward";
4887 ActionLog =
" changed direction under signaller control at ";
4889 ActionLog =
" received signaller authority to pass red signal";
4891 ActionLog =
" received signaller instruction to stop";
4893 ActionLog =
" stopped on signaller instruction ";
4895 ActionLog =
" joined under signaller control by ";
4897 ActionLog =
" suffered an onboard power failure at ";
4899 ActionLog =
" failure repaired at ";
4901 ActionLog =
" left railway under signaller control at ";
4902 if(OtherHeadCode !=
"")
4903 OtherHeadCode +=
" at ";
4909 WarningBaseLog =
HeadCode + ActionLog + OtherHeadCode + LocationName;
4915 bool TimePerformance =
true;
4923 TimePerformance =
false;
4927 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
4937 IntMinsLate = int(ceil(MinsLate));
4941 IntMinsLate = int(floor(MinsLate));
4943 if(IntMinsLate == 0)
4945 PerfLog =
" on time";
4947 else if(IntMinsLate == 1)
4948 PerfLog =
" 1 minute late";
4949 else if(IntMinsLate == -1)
4950 PerfLog =
" 1 minute early";
4951 else if(IntMinsLate > 1)
4952 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
4953 else if(IntMinsLate < -1)
4955 int PosIntMinsLate = -IntMinsLate;
4956 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
4958 if(LocationName.Pos(
'-') > 0)
4960 PerfLog =
"," + PerfLog;
4973 if((ActionType ==
Arrive) && (IntMinsLate == 0))
4977 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
4982 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
4987 else if((ActionType ==
Pass) && (IntMinsLate == 0))
4991 else if((ActionType ==
Pass) && (IntMinsLate > 0))
4996 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5001 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5005 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5024 AnsiString LocName =
"";
5088 if(LocationName ==
"")
5090 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5091 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5092 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5096 if(LocationName !=
"")
5104 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5109 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5123 int LeadPosA = FirstNamedElementPos;
5124 int LeadPosB = FirstNamedLinkedElementPos;
5125 int LeadPosC = SecondNamedElementPos;
5126 int LeadPosD = SecondNamedLinkedElementPos;
5128 int LeadNumAtLoc = 0;
5137 if(LeadNumAtLoc < 4)
5141 SecondNamedLinkedElementPos))
5143 FirstNamedElementPos = LeadPosA;
5144 FirstNamedLinkedElementPos = LeadPosB;
5145 SecondNamedElementPos = LeadPosC;
5146 SecondNamedLinkedElementPos = LeadPosD;
5150 int MidNumAtLoc = 0;
5159 if(LeadNumAtLoc > MidNumAtLoc)
5162 FirstNamedElementPos = LeadPosA;
5163 FirstNamedLinkedElementPos = LeadPosB;
5164 SecondNamedElementPos = LeadPosC;
5165 SecondNamedLinkedElementPos = LeadPosD;
5178 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5187 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5188 FrontTrainRearPosition = FirstNamedElementPos;
5189 RearTrainFrontPosition = SecondNamedElementPos;
5190 RearTrainRearPosition = SecondNamedLinkedElementPos;
5194 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5195 FrontTrainRearPosition = SecondNamedElementPos;
5196 RearTrainFrontPosition = FirstNamedElementPos;
5197 RearTrainRearPosition = FirstNamedLinkedElementPos;
5204 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5205 FrontTrainRearPosition = SecondNamedElementPos;
5206 RearTrainFrontPosition = FirstNamedElementPos;
5207 RearTrainRearPosition = FirstNamedLinkedElementPos;
5211 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5212 FrontTrainRearPosition = FirstNamedElementPos;
5213 RearTrainFrontPosition = SecondNamedElementPos;
5214 RearTrainRearPosition = SecondNamedLinkedElementPos;
5217 RearTrainExitPos = -1;
5218 for(
int x = 0; x < 4; x++)
5222 RearTrainExitPos = x;
5226 if(RearTrainExitPos == -1)
5227 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5229 FrontTrainExitPos = -1;
5230 for(
int x = 0; x < 4; x++)
5234 FrontTrainExitPos = x;
5238 if(FrontTrainExitPos == -1)
5239 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5242 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5247 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5261 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5266 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5267 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5268 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5364 if(LocationName ==
"")
5366 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5367 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5368 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5372 if(LocationName !=
"")
5379 SecondNamedLinkedElementPos))
5383 SecondNamedLinkedElementPos))
5397 int LeadPosA = FirstNamedElementPos;
5398 int LeadPosB = FirstNamedLinkedElementPos;
5399 int LeadPosC = SecondNamedElementPos;
5400 int LeadPosD = SecondNamedLinkedElementPos;
5402 int LeadNumAtLoc = 0;
5411 if(LeadNumAtLoc < 4)
5415 SecondNamedLinkedElementPos))
5417 FirstNamedElementPos = LeadPosA;
5418 FirstNamedLinkedElementPos = LeadPosB;
5419 SecondNamedElementPos = LeadPosC;
5420 SecondNamedLinkedElementPos = LeadPosD;
5424 int MidNumAtLoc = 0;
5433 if(LeadNumAtLoc > MidNumAtLoc)
5436 FirstNamedElementPos = LeadPosA;
5437 FirstNamedLinkedElementPos = LeadPosB;
5438 SecondNamedElementPos = LeadPosC;
5439 SecondNamedLinkedElementPos = LeadPosD;
5452 throw Exception(
"Error - LocationName not set in RearTrainSplit");
5461 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5462 FrontTrainRearPosition = FirstNamedElementPos;
5463 RearTrainFrontPosition = SecondNamedElementPos;
5464 RearTrainRearPosition = SecondNamedLinkedElementPos;
5468 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5469 FrontTrainRearPosition = SecondNamedElementPos;
5470 RearTrainFrontPosition = FirstNamedElementPos;
5471 RearTrainRearPosition = FirstNamedLinkedElementPos;
5478 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5479 FrontTrainRearPosition = SecondNamedElementPos;
5480 RearTrainFrontPosition = FirstNamedElementPos;
5481 RearTrainRearPosition = FirstNamedLinkedElementPos;
5485 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5486 FrontTrainRearPosition = FirstNamedElementPos;
5487 RearTrainFrontPosition = SecondNamedElementPos;
5488 RearTrainRearPosition = SecondNamedLinkedElementPos;
5491 RearTrainExitPos = -1;
5492 for(
int x = 0; x < 4; x++)
5496 RearTrainExitPos = x;
5500 if(RearTrainExitPos == -1)
5501 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
5502 FrontTrainExitPos = -1;
5503 for(
int x = 0; x < 4; x++)
5507 FrontTrainExitPos = x;
5511 if(FrontTrainExitPos == -1)
5512 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
5515 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5520 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5534 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5539 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5540 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5541 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5678 TTrain *TrainToBeJoinedBy;
5709 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
5711 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
5766 int RouteNumber = -1;
5872 for(
int x = 0; x < IncNum; x++)
5903 else if(Ptr->
Command ==
"jbo")
5914 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
5920 bool IncludeFER =
false;
5926 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
5931 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
5942 else if(Ptr->
Command ==
"Fjo")
5948 else if(Ptr->
Command ==
"Frh")
5958 else if(Ptr->
Command ==
"Frh-sh")
6009 else if(Ptr->
Command ==
"jbo")
6014 else if(Ptr->
Command ==
"cdt")
6022 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6385 int RouteNumber = -1;
6420 ",FloatingLabelNextString" +
"," +
HeadCode);
6421 AnsiString RetStr =
"", LocationName =
"";
6425 throw Exception(
"Error - start entry in FloatingLabelNextString");
6465 else if(Ptr->
Command ==
"Fns")
6471 else if(Ptr->
Command ==
"F-nshs")
6502 RetStr =
"None, train terminated at " + Ptr->
LocationName;
6504 else if(Ptr->
Command ==
"Frh")
6506 RetStr =
"None, train terminated at " + Ptr->
LocationName;
6508 else if(Ptr->
Command ==
"Fer")
6510 AnsiString AllowedExits =
"";
6513 else if(Ptr->
Command ==
"Fjo")
6518 else if(Ptr->
Command ==
"jbo")
6523 else if(Ptr->
Command ==
"fsp")
6528 else if(Ptr->
Command ==
"rsp")
6533 else if(Ptr->
Command ==
"cdt")
6546 + AnsiString(RptNum) +
",CheckNewServiceDepartureTime," +
HeadCode);
6547 AnsiString DepTime =
"", EventTime =
"";
6548 bool CDTFlag =
false;
6552 if(AVI->Command ==
"cdt")
6557 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
6560 RetStr +=
"\nNew service splits at " + EventTime;
6564 if(AVI->Command ==
"jbo")
6567 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
6571 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
6576 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
6580 RetStr +=
"\nNew service departs at " + DepTime;
6596 ",FloatingTimetableString" +
"," +
HeadCode);
6597 AnsiString RetStr =
"", PartStr =
"";
6603 throw Exception(
"Error - start entry in FloatingTimetableString");
6606 bool FirstPass =
true;
6617 AnsiString TrainLoc =
"";
6655 AnsiString TrainLoc =
"";
6683 else if(Ptr->
Command ==
"Fns")
6689 else if(Ptr->
Command ==
"F-nshs")
6722 else if(Ptr->
Command ==
"Frh")
6726 else if(Ptr->
Command ==
"Fer")
6728 AnsiString AllowedExits =
"";
6731 else if(Ptr->
Command ==
"Fjo")
6736 else if(Ptr->
Command ==
"jbo")
6741 else if(Ptr->
Command ==
"fsp")
6746 else if(Ptr->
Command ==
"rsp")
6751 else if(Ptr->
Command ==
"cdt")
6756 RetStr = RetStr +
'\n' + PartStr;
6769 RetStr =
"Timetable finished";
6771 RetStr =
"No timetable";
6897 bool ForwardHeadCode;
6901 ForwardHeadCode =
true;
6906 ForwardHeadCode =
false;
7039 if(ColourNumber == 0)
7041 else if(ColourNumber == 1)
7043 else if(ColourNumber == 2)
7045 else if(ColourNumber == 3)
7047 else if(ColourNumber == 4)
7049 else if(ColourNumber == 5)
7051 else if(ColourNumber == 6)
7053 else if(ColourNumber == 7)
7055 else if(ColourNumber == 8)
7057 else if(ColourNumber == 9)
7059 else if(ColourNumber == 10)
7061 else if(ColourNumber == 11)
7063 else if(ColourNumber == 12)
7065 else if(ColourNumber == 13)
7067 else if(ColourNumber == 14)
7077 for(
int x = 0; x < 4; x++)
7084 for(
int x = 0; x < 4; x++)
7149 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
7152 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
7153 bool GiveMessagesFalse =
false;
7154 bool CheckLocationsExistInRailwayTrue =
true;
7160 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
7163 if(Marker[6] ==
'1')
7460 bool HideFlashingTrain =
true;
7463 Graphics::TBitmap *SmallTrainBitmap;
7504 HideFlashingTrain =
false;
7509 HideFlashingTrain =
false;
7514 HideFlashingTrain =
false;
7519 HideFlashingTrain =
false;
7524 HideFlashingTrain =
false;
7529 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
7533 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
7557 for(
int y = 0; y < 3; y++)
7561 bool FoundFlag =
false;
7572 if(IMPair.first != IMPair.second)
7599 if((LocationName ==
"") && (
MidElement > -1))
7603 if((LocationName ==
"") && (
LagElement > -1))
7607 if(LocationName ==
"")
7609 throw Exception(
"Error - Location name not set in TrainAtLocation");
7620 for(
int x = 0; x < 4; x++)
7632 for(
int x = 0; x < 4; x++)
7649 AnsiString(LinkNumber) +
"," +
HeadCode);
7700 int DistanceToRedSignal = 0;
7701 float TimeToAct = 0;
7702 float MinsEarly = 0;
7703 TDateTime DepartureTime;
7752 float CurrentStopTime;
7753 float LaterStopTime;
7754 float RecoverableTime;
7759 if(DistanceToRedSignal == -1)
7778 float TimeToSubtract, TotalStopTime;
7780 TimeToSubtract = RecoverableTime;
7806 if(CurrentStopTime > 0)
7807 TotalStopTime = CurrentStopTime + LaterStopTime;
7813 else if((MinsEarly > 0) && !
Stopped())
7815 TotalStopTime = LaterStopTime + MinsEarly;
7819 if(LaterStopTime == 0)
7820 TotalStopTime = CurrentStopTime;
7824 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
7827 if(AvTrackSpeed < 30)
7829 int Speed = AvTrackSpeed;
7837 TimeToAct = TotalStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
7857 if((NextEntryPos == 0) || (NextEntryPos == 2))
7969 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8010 int IncrementalMinutes = 0;
8011 int IncrementalDigits = 0;
8019 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
8045 if(AVEntry0.
Command ==
"Snt-sh")
8050 int IncrementalMinutes = 0;
8051 int IncrementalDigits = 0;
8059 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
8092 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8152 AnsiString Loc =
"";
8153 bool ElementFound =
false;
8158 ElementFound =
true;
8163 ElementFound =
true;
8168 ElementFound =
true;
8198 else if(AVEntryPtr->
Command ==
"Fer")
8200 bool CorrectExit =
false;
8308 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8323 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8338 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8349 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
8350 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
8351 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
8353 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
8354 "," + AnsiString(Mass) +
"," + ModeStr);
8356 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr +
"," + HeadCode);
8358 int RearExitPos = -1;
8360 for(
int x = 0; x < 4; x++)
8367 if(RearExitPos == -1)
8369 throw Exception(
"Error, RearExit == -1 in AddTrain");
8372 bool ReportFlag =
true;
8388 if(ModeStr ==
"Timetable")
8392 if(MaxRunningSpeed < 10)
8394 MaxRunningSpeed = 10;
8396 if(SignallerSpeed < 10)
8397 SignallerSpeed = 10;
8398 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
8399 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
8404 if(SignallerControl)
8435 if(!SignallerControl)
8450 if(!SignallerControl)
8461 AnsiString Loc =
"";
8478 if(!SignallerControl)
8499 int RouteNumber = -1;
8500 bool SignalsSet =
false;
8506 int RouteStartPosition;
8510 if(FirstPair.first == RouteNumber)
8512 RouteStartPosition = FirstPair.second;
8514 else if(SecondPair.first == RouteNumber)
8516 RouteStartPosition = SecondPair.second;
8520 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
8526 else if(RouteNumber > -1)
8546 int LinkedRouteNumber = -1;
8565 int RouteStartPosition;
8569 if(FirstPair.first == RouteNumber)
8571 RouteStartPosition = FirstPair.second;
8573 else if(SecondPair.first == RouteNumber)
8575 RouteStartPosition = SecondPair.second;
8579 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
8585 else if(RouteNumber > -1)
8605 int LinkedRouteNumber = -1;
8627 AnsiString(TrackVectorNumber));
8630 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8639 throw Exception(
"Error, VecPos not set in EntryPos");
8641 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
8646 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
8651 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
8665 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8673 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
8683 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8713 AnsiString RetStr =
"", PartStr =
"";
8721 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
8727 if(Ptr->SignallerControl)
8729 RetStr =
"Train under signaller control";
8734 if(Ptr->ArrivalTime == Ptr->DepartureTime)
8745 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
8749 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
8753 else if(Ptr->FormatType ==
PassTime)
8757 else if(Ptr->Command ==
"Fns")
8763 else if(Ptr->Command ==
"F-nshs")
8766 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
8773 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
8780 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
8783 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
8786 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
8793 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
8795 PartStr =
"Terminate at " + Ptr->LocationName;
8797 else if(Ptr->Command ==
"Frh")
8799 PartStr =
"Terminate at " + Ptr->LocationName;
8801 else if(Ptr->Command ==
"Fer")
8803 AnsiString AllowedExits;
8807 else if(Ptr->Command ==
"Fjo")
8810 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
8812 else if(Ptr->Command ==
"jbo")
8815 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
8817 else if(Ptr->Command ==
"fsp")
8822 else if(Ptr->Command ==
"rsp")
8827 else if(Ptr->Command ==
"cdt")
8832 RetStr = RetStr +
'\n' + PartStr;
8837 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
8850 + AnsiString(RptNum) +
",ControllerCheckNewServiceDepartureTime," + TDEPtr->
HeadCode);
8851 AnsiString DepTime =
"", EventTime =
"";
8852 bool CDTFlag =
false;
8856 if(AVI->Command ==
"cdt")
8861 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
8864 RetStr +=
"\nNew service splits at " + EventTime;
8868 if(AVI->Command ==
"jbo")
8871 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
8875 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
8880 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
8884 RetStr +=
"\nNew service departs at " + DepTime;
9042 ActiveTrackElementNameMapEntry.first =
Track->
TrackVector.at(x).ActiveTrackElementName;
9043 ActiveTrackElementNameMapEntry.second = 0;
9049 std::ifstream TTBLFile(FileName, std::ios_base::binary);
9052 if(TTBLFile.is_open())
9054 char *TrainTimetableString =
new char[10000];
9056 bool EndOfFile =
false;
9059 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9061 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9067 delete TrainTimetableString;
9071 AnsiString OneLine(TrainTimetableString);
9072 bool FinalCallFalse =
false;
9073 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
9077 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9078 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9082 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
9084 delete TrainTimetableString;
9088 OneLine = AnsiString(TrainTimetableString);
9094 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9096 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9104 OneLine = AnsiString(TrainTimetableString);
9105 if(OneLine.Length() > 9999)
9107 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
9109 delete TrainTimetableString;
9113 bool FinalCallFalse =
false;
9114 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
9118 delete TrainTimetableString;
9122 if(EndOfFile && (Count < 2))
9125 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
9127 delete TrainTimetableString;
9133 delete TrainTimetableString;
9138 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's not open in another application");
9149 bool CheckLocationsExistInRailway)
9274 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
9284 if(OneLine[1] !=
'*')
9286 int SCPos = OneLine.Pos(
';');
9293 bool AllCommas =
true;
9295 for(
int x = 1; x < OneLine.Length() + 1; x++)
9297 if(OneLine[x] !=
',')
9300 if(AllCommas || (OneLine ==
""))
9315 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
9316 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
9317 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
9318 TDateTime StartTime(0);
9320 bool Warning =
false;
9347 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
9348 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
9349 double MaxBrakeRate = 0;
9350 double PowerAtRail = 0;
9351 int SignallerSpeed = 0;
9352 if(OneLine[1] ==
'*')
9358 int Pos = OneLine.Pos(
',');
9361 int SubStringLength = 20;
9362 if(OneLine.Length() < 20)
9363 SubStringLength = OneLine.Length();
9364 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
9368 TrainInfoStr = OneLine.SubString(1, Pos - 1);
9369 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
9379 TempTrainDataEntry.
HeadCode = HeadCode;
9383 TempTrainDataEntry.
Mass = Mass;
9391 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
9394 while(NewRemainder[NewRemainder.Length()] ==
',')
9396 if(NewRemainder.Length() > 1)
9398 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
9407 if(NewRemainder ==
"")
9409 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
9415 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
9417 if(NewRemainder[x] ==
',')
9422 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
9424 int SubStringLength = 20;
9425 if(OneLine.Length() < 20)
9426 SubStringLength = OneLine.Length();
9428 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
9429 OneLine.SubString(1, SubStringLength) +
"'....");
9434 AnsiString OneEntry =
"";
9439 bool FinishFlag =
false;
9440 for(
int x = 0; x < CommaCount + 1; x++)
9442 if((CommaCount == 0) || (x < CommaCount))
9449 OneEntry = NewRemainder;
9454 Pos = NewRemainder.Pos(
',');
9455 OneEntry = NewRemainder.SubString(1, Pos - 1);
9456 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
9462 RearStartOrRepeatMins = 0;
9463 FrontStartOrRepeatDigits = 0;
9464 NumberOfRepeats = 0;
9465 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
9466 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
9468 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
9473 if(Warning && (Second ==
"Frh"))
9475 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
9479 if(Warning && (Second ==
"Fjo"))
9482 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
9488 if(SequenceType !=
Start)
9490 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
9494 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
9496 if(NewRemainder[1] !=
'R')
9499 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
9505 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
9509 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
9512 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
9518 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
9523 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
9528 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
9531 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
9538 if(SequenceType ==
Finish)
9553 ActionVectorEntry.
Warning = Warning;
9566 ActionVectorEntry.
Command = Second;
9579 else if(FormatType ==
TimeCmd)
9584 ActionVectorEntry.
Command = Second;
9591 ActionVectorEntry.
Command = Second;
9592 ActionVectorEntry.
ExitList = ExitList;
9599 ActionVectorEntry.
Command = Second;
9610 ActionVectorEntry.
Command = Second;
9620 ActionVectorEntry.
Command = Second;
9629 ActionVectorEntry.
Command = Second;
9637 ActionVectorEntry.
Command = Second;
9645 ActionVectorEntry.
Command = Second;
9651 ActionVectorEntry.
Command = Second;
9653 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
9658 OneEntry = NewRemainder;
9663 RearStartOrRepeatMins = 0;
9664 FrontStartOrRepeatDigits = 0;
9665 NumberOfRepeats = 0;
9666 if((FinishFlag) && (OneEntry[1] !=
'R'))
9669 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
9673 if(OneEntry[1] !=
'R')
9675 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
9676 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
9678 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
9682 if(SequenceType !=
Finish)
9684 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
9697 ActionVectorEntry.
Warning = Warning;
9703 ActionVectorEntry.
Command = Second;
9710 ActionVectorEntry.
Command = Second;
9718 ActionVectorEntry.
Command = Second;
9726 ActionVectorEntry.
Command = Second;
9735 ActionVectorEntry.
Command = Second;
9736 ActionVectorEntry.
ExitList = ExitList;
9740 ActionVectorEntry.
Command = Second;
9742 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
9747 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
9763 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
9782 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
9787 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
9802 if(TimeStr.Length() < 5)
9807 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
9812 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
9817 if(TimeStr[3] !=
':')
9822 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
9827 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
9832 while(TimeStr.Length() > 5)
9833 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
9834 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
9835 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
9837 if((WholeHours + FracHour) >= 95.98334)
9842 Time = TDateTime((WholeHours + FracHour) / 24);
9849 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
9850 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
9861 if(OneEntry.Length() > 0)
9863 if(OneEntry[1] ==
'W')
9866 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
9870 if(OneEntry ==
"Frh")
9880 if(OneEntry.Length() < 7)
9885 int Pos = OneEntry.Pos(
';');
9893 First = OneEntry.SubString(1, 5);
9899 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
9901 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
9904 if(Remainder.Length() < 7)
9909 Pos = Remainder.Pos(
';');
9916 Second = Remainder.SubString(1, 5);
9922 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
9935 Pos = Remainder.Pos(
';');
9964 if((Pos != 4) && (Pos != 7) && (Pos != 8))
9970 Second = Remainder.SubString(1, Pos - 1);
9972 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
9974 Pos = Remainder.Pos(
';');
9979 Third = Remainder.SubString(1, Pos - 1);
9980 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
9982 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
9985 int SpacePos = Third.Pos(
' ');
9991 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
9992 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
9994 if(CheckLocationsExistInRailway)
10004 if(Second ==
"Snt")
10007 SequenceType =
Start;
10016 SequenceType =
Start;
10028 if(Second ==
"Sns-sh")
10032 SequenceType =
Start;
10048 if(Second ==
"F-nshs")
10063 if(Second ==
"Sns-fsh")
10067 SequenceType =
Start;
10078 if(Second ==
"Fns-sh")
10099 if(Second ==
"pas")
10115 if(Second ==
"Fer")
10122 if(CheckLocationsExistInRailway)
10135 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
10136 (Second !=
"Frh-sh"))
10149 if(Second ==
"Frh-sh")
10153 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
10157 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
10161 if((Second ==
"Sfs") || (Second ==
"Sns"))
10163 SequenceType =
Start;
10181 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
10186 for(
int x = 1; x < LocStr.Length() + 1; x++)
10188 if(LocStr[x] <
' ')
10193 if(LocStr[x] >
'z')
10200 if(CheckLocationsExistInRailway)
10205 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
10206 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
10207 "that includes a continuation will not be valid.");
10225 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
10228 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Snt-sh, Sns-sh, Fns-sh or Frh-sh");
10233 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
10235 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
10237 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
10243 for(
int x = 3; x >= 0; x--)
10245 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
10246 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
10248 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
10264 AnsiString CurrentID =
"";
10266 if(IDSet.Length() == 0)
10268 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
10272 for(
int x = 1; x <= IDSet.Length(); x++)
10275 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
10277 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
10282 int Pos = IDSet.Pos(
' ');
10293 CurrentID = IDSet.SubString(1, Pos - 1);
10294 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
10306 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
10313 if(!ExitList.empty())
10317 if(*ELIT == VecPos)
10319 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
10326 ExitList.push_back(VecPos);
10336 Pos = IDSet.Pos(
' ');
10343 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
10350 AnsiString Remainder =
"";
10351 int SemiColonCount = 0;
10353 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
10355 if(TrainInfoStr[x] ==
';')
10358 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
10360 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
10361 "'. Should be headcode + optional description for a continuing service;" +
10362 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
10366 if(SemiColonCount == 0)
10368 HeadCode = TrainInfoStr;
10377 if(SemiColonCount == 1)
10379 Pos = TrainInfoStr.Pos(
';');
10380 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
10381 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
10387 if(Description ==
"")
10389 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
10393 if(Description.Length() > 60)
10395 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
10399 for(
int x = 1; x < Description.Length() + 1; x++)
10401 if((Description[x] <
' ') || (Description[x] >
'~'))
10403 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
10412 Pos = TrainInfoStr.Pos(
';');
10413 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
10414 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
10420 Pos = Remainder.Pos(
';');
10421 Description = Remainder.SubString(1, Pos - 1);
10422 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10423 if(Description ==
"")
10425 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
10429 if(Description.Length() > 60)
10431 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
10435 for(
int x = 1; x < Description.Length() + 1; x++)
10437 if((Description[x] <
' ') || (Description[x] > 126))
10439 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
10444 Pos = Remainder.Pos(
';');
10445 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
10447 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10448 if(StartSpeedStr ==
"")
10450 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
10454 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
10456 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
10458 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
10463 StartSpeed = StartSpeedStr.ToInt();
10469 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
10473 Pos = Remainder.Pos(
';');
10474 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
10476 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10477 if(MaxRunningSpeedStr ==
"")
10479 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
10483 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
10485 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
10487 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
10492 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
10498 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
10502 if(MaxRunningSpeed < 10)
10505 MaxRunningSpeed = 10;
10508 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
10512 Pos = Remainder.Pos(
';');
10513 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
10515 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10518 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
10522 for(
int x = 1; x < MassStr.Length() + 1; x++)
10524 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
10526 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
10531 Mass = MassStr.ToInt() * 1000;
10537 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
10543 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
10547 Pos = Remainder.Pos(
';');
10548 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
10550 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10551 if(MaxBrakeForceStr ==
"")
10553 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
10557 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
10559 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
10561 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
10566 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
10569 if((MaxBrakeForce / Mass) > 1)
10571 MaxBrakeForce = Mass;
10574 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
10578 if((MaxBrakeForce / Mass) < 0.01)
10580 MaxBrakeForce = Mass * 0.01;
10583 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
10588 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
10590 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
10592 if(SemiColonCount == 6)
10594 GrossPowerStr = Remainder;
10595 SignallerSpeedStr =
"30";
10599 Pos = Remainder.Pos(
';');
10600 GrossPowerStr = Remainder.SubString(1, Pos - 1);
10601 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10604 if(GrossPowerStr ==
"")
10606 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
10610 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
10612 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
10614 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
10620 double GrossPower = GrossPowerStr.ToInt() * 1000;
10627 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
10631 else if(GrossPower == 0)
10636 else if((GrossPower > 0) && (GrossPower < 10000))
10639 GrossPower = 10000;
10641 PowerAtRail = GrossPower * 0.8;
10645 if(SignallerSpeedStr ==
"")
10647 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
10651 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
10653 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
10655 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
10660 SignallerSpeed = SignallerSpeedStr.ToInt();
10666 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
10670 if(SignallerSpeed < 10)
10673 SignallerSpeed = 10;
10676 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
10694 if(OneEntry.Length() < 7)
10696 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
10700 int SemiColonCount = 0;
10702 for(
int x = 1; x < OneEntry.Length() + 1; x++)
10704 if(OneEntry[x] ==
';')
10707 if(SemiColonCount != 3)
10709 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
10713 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
10715 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
10719 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
10724 Pos = Remainder.Pos(
';');
10725 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
10727 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10728 if(MinutesStr ==
"")
10730 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
10734 if(MinutesStr.Length() > 3)
10737 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
10741 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
10743 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
10745 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
10750 RearStartOrRepeatMins = MinutesStr.ToInt();
10751 if(RearStartOrRepeatMins == 0)
10753 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
10757 Pos = Remainder.Pos(
';');
10758 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
10760 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10761 if(DigitsStr ==
"")
10763 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
10767 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
10769 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
10771 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
10776 if(DigitsStr.Length() > 2)
10778 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
10782 FrontStartOrRepeatDigits = DigitsStr.ToInt();
10796 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
10800 AnsiString NumberStr = Remainder;
10802 if(NumberStr ==
"")
10804 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
10808 if(NumberStr.Length() > 4)
10811 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
10815 for(
int x = 1; x < NumberStr.Length() + 1; x++)
10817 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
10820 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
10825 NumberOfRepeats = NumberStr.ToInt();
10826 if(NumberOfRepeats == 0)
10828 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
10984 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
11008 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
11022 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
11038 "Error in timetable - a signaller control service can have no more than one item (a repeat) after the start event, see: " +
11050 "Error in timetable - a signaller control service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
11077 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
11088 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11093 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
11103 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11108 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
11118 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11129 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
11139 SecondPassMessage(GiveMessages,
"Error in timetable - the last event before the repeat must be a finish for: " + TDEntry.
HeadCode);
11151 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11158 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
11167 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " +
11187 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
11189 AnsiString LocationName =
"";
11205 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
11206 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
11215 SecondPassMessage(GiveMessages,
"Error in timetable - 'Snt' or 'Snt-sh' event at stop location but start speed not zero for: " +
11224 if(AVEntry0.
Command ==
"Snt-sh")
11238 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
11254 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' followed by an illegal event for: " +
11255 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
11266 bool FoundFlag =
false;
11272 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11284 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sfs', 'Sns', 'Sns-sh'or 'Sns-fsh' event for: " +
11297 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11306 ": an event should have had a location name associated with it but it could not be found");
11312 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
11332 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11342 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
11349 if(AVEntry.
Command ==
"F-nshs")
11354 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
11382 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
11383 ". The event isn't valid for a stationary train.");
11393 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
11401 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
11402 ". The event isn't valid for a stationary train.");
11420 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
11421 ". The event isn't valid for a stationary train.");
11431 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
11439 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
11440 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
11458 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
11459 ". The event isn't valid for a moving train.");
11481 bool LastEntryIsAnArrival =
false;
11488 LastEntryIsAnArrival =
false;
11489 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11496 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
11498 if(LastEntryIsAnArrival)
11502 LastEntryIsAnArrival =
false;
11508 LastEntryIsAnArrival =
true;
11515 LastEntryIsAnArrival =
true;
11516 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11523 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
11525 if(LastEntryIsAnArrival)
11529 LastEntryIsAnArrival =
false;
11535 LastEntryIsAnArrival =
true;
11545 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11553 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
11561 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
11562 ". The event isn't valid for a stationary train.");
11573 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
11581 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
11582 ". The event isn't valid for a moving train.");
11596 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11603 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
11607 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
11614 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
11618 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
11627 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
11631 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
11638 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
11649 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11660 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
11668 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
11683 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
11695 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
11707 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
11708 ", may be before timetable start time");
11719 AnsiString LastLocationName =
"";
11723 bool LastEntryIsAnArrival =
false;
11728 LastEntryIsAnArrival =
false;
11729 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
11730 if(LastLocationName !=
"")
11732 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
11734 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
11745 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
11757 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
11769 ShowMessage(
"Two or more locations are the same without a change of direction between them. Please correct if this is an error.\n\nThis warning will not be shown again.");
11778 LastEntryIsAnArrival =
false;
11782 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
11785 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
11790 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
11793 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
11799 LastEntryIsAnArrival = !LastEntryIsAnArrival;
11805 LastEntryIsAnArrival =
true;
11806 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
11807 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11817 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
11829 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
11841 ShowMessage(
"Two or more locations are the same without a change of direction between them. Please correct if this is an error.\n\nThis warning will not be shown again.");
11850 LastEntryIsAnArrival =
false;
11854 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
11857 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
11865 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
11872 LastEntryIsAnArrival = !LastEntryIsAnArrival;
11880 AnsiString LocationNameToBeChecked =
"";
11885 unsigned int y = 0;
11900 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
11901 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
11917 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
11925 ShowMessage(
"Two or more locations are the same without a change of direction between them. Please correct if this is an error.\n\nThis warning will not be shown again.");
11944 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11949 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
11951 AnsiString LocName =
"";
11957 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
11964 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
11987 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12012 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12034 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12056 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12075 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12078 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
12093 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12098 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
12102 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
12106 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
12110 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
12147 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12149 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
12155 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
12168 int IncMinutes = 0;
12176 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12182 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
12188 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
12193 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
12199 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
12204 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
12217 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12243 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
12251 if(HeadCode.Length() > 4)
12253 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
12264 int ForwardCount = 0;
12265 int ReverseCount = 0;
12267 if(MainHeadCode == SecondHeadCode)
12269 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
12279 if(TDEntry.
HeadCode == MainHeadCode)
12281 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12296 if(ForwardCount == 0)
12299 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
12302 if(ForwardCount > 2)
12305 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
12306 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
12316 if(TDEntry.
HeadCode == SecondHeadCode)
12318 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12333 if(ReverseCount == 0)
12335 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
12340 if(ReverseCount > 2)
12343 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
12344 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
12350 if(ForwardCount != ReverseCount)
12352 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
12353 " than the other way round");
12385 int ForwardCount = 0;
12386 int ReverseCount = 0;
12387 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
12396 if(TDEntry.
HeadCode == MainHeadCode)
12398 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12401 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
12406 ForwardEntryPtr = &AVEntry;
12408 ForwardTDVectorNumber = x;
12411 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
12412 (AVEntry.
Command ==
"Frh-sh")))
12417 ForwardEntryPtr = &AVEntry;
12419 ForwardTDVectorNumber = x;
12425 if(ForwardCount == 0)
12428 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
12430 if(ForwardCount > 1)
12432 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
12443 if(TDEntry.
HeadCode == OtherHeadCode)
12445 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12448 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
12454 ReverseEntryPtr = &AVEntry;
12455 ReverseTDVectorNumber = x;
12458 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
12464 ReverseEntryPtr = &AVEntry;
12465 ReverseTDVectorNumber = x;
12472 if(ReverseCount == 0)
12474 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
12479 if(ReverseCount > 1)
12481 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
12489 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
12490 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
12491 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
12492 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
12496 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
12504 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
12510 if(ForwardEntryPtr->LocationName ==
"")
12512 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
12513 ". One or other service does not have a location set");
12521 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
12522 ". One or other service does not have a location set");
12528 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
12530 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
12531 " is at a different location to the referencing train " + MainHeadCode);
12540 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
12542 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
12543 " has a different event time to the referencing train " + MainHeadCode);
12552 if(ForwardShuttleStart && ReverseShuttleFinish)
12557 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
12558 " first repeat restart time not consistent with finish service " + OtherHeadCode);
12565 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
12568 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
12570 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
12571 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
12578 if(ReverseEntryPtr->
Command ==
"Fjo")
12581 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
12583 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
12584 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
12591 if(ReverseEntryPtr->
Command ==
"Fns")
12594 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
12596 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
12597 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
12604 if(ForwardEntryPtr->Command ==
"Sfs")
12606 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
12609 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
12617 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
12619 if(ReverseEntryPtr->
Command !=
"Sfs")
12621 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
12631 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
12638 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
12645 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
12650 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
12660 if(ForwardEntryPtr->Command ==
"Sns")
12662 if(ReverseEntryPtr->
Command !=
"Fns")
12664 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
12665 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
12672 if(ForwardEntryPtr->Command ==
"Fns")
12674 if(ReverseEntryPtr->
Command !=
"Sns")
12676 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
12677 " and forms a new service with headcode " + OtherHeadCode);
12684 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
12693 if(ForwardEntryPtr->Command ==
"jbo")
12695 if(ReverseEntryPtr->
Command !=
"Fjo")
12697 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
12698 " and is joined by a train with headcode " + OtherHeadCode);
12705 if(ForwardEntryPtr->Command ==
"Fjo")
12707 if(ReverseEntryPtr->
Command !=
"jbo")
12709 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
12710 " and joins a train with headcode " + OtherHeadCode);
12717 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
12726 if(ForwardShuttleStart)
12729 if(!ReverseShuttleFinish)
12732 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
12733 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
12740 if(ReverseShuttleStart)
12743 if(!ForwardShuttleFinish)
12746 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
12747 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
12754 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
12767 bool MainRepeat =
false, OtherRepeat =
false;
12777 OtherRepeat =
true;
12780 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
12782 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
12783 " and the associated train with headcode " + OtherHeadCode);
12788 if(MainRepeat && OtherRepeat)
12794 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
12795 " and the associated train with headcode " + OtherHeadCode);
12817 while(Input[1] ==
' ')
12819 if(Input.Length() > 1)
12821 Input = Input.SubString(2, Input.Length() - 1);
12835 while(Input[Input.Length()] ==
' ')
12837 if(Input.Length() > 1)
12839 Input = Input.SubString(1, Input.Length() - 1);
12849 AnsiString Output =
"";
12850 bool DelimiterFound =
false;
12852 for(
int x = 1; x < Input.Length() + 1; x++)
12856 if(Input[x] ==
' ')
12859 if((Input[x] !=
',') && (Input[x] !=
';'))
12861 DelimiterFound =
false;
12862 Output = Output + Input[x];
12866 DelimiterFound =
true;
12867 Output = Output + Input[x];
12879 DelimiterFound =
false;
12880 for(
int x = Input.Length(); x > 0; x--)
12884 if(Input[x] ==
' ')
12887 if((Input[x] !=
',') && (Input[x] !=
';'))
12889 DelimiterFound =
false;
12890 Output = AnsiString(Input[x]) + Output;
12894 DelimiterFound =
true;
12895 Output = AnsiString(Input[x]) + Output;
12915 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
12917 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
12928 LocationName = LocRear;
12930 LocationName = LocFront;
12931 if(LocationName ==
"")
12957 AnsiString TimeLocLocationName;
12958 bool FoundFlag =
false;
12960 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
12975 if(TimeLocLocationName == LocationName)
12992 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
12995 if(RearPosition < 0)
13002 if(FrontPosition < 0)
13013 for(
int x = 0; x < 4; x++)
13015 if(RearTrackElement.
Conn[x] == FrontPosition)
13030 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
13038 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
13044 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
13050 if((RearType ==
Points) && (RearExitPos == 3))
13052 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
13059 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
13074 AnsiString(RearExitPos));
13081 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
13083 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
13086 AnsiString RearName, FrontName;
13095 FrontName = FrontTrackElement.
ElementID;
13098 int LockedVectorNumber;
13233 "," + AnsiString(IncDigits));
13236 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
13241 return BaseHeadCode;
13243 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
13244 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
13246 while(NextRepeatDigits >= 100)
13248 NextRepeatDigits -= 100;
13250 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
13252 if(NextRepeatDigitsStr.Length() < 2)
13253 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
13254 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
13257 return NextRepeatHeadCode;
13265 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
13266 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
13269 return NextRepeatTime;
13278 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
13279 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
13280 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
13281 int RepeatSecs = RepeatMinutes * 60;
13283 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
13301 NonRepeatingHeadCode);
13302 int ForwardCount = 0;
13303 int ReverseCount = 0;
13304 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
13314 if(TDEntry.
HeadCode == MainHeadCode)
13316 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13322 ForwardEntryPtr = &AVEntry;
13324 ForwardTDVectorNumber = x;
13329 if(ForwardCount == 0)
13332 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
13334 if(ForwardCount > 1)
13336 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
13347 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
13349 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13356 ReverseEntryPtr = &AVEntry;
13357 ReverseTDVectorNumber = x;
13363 if(ReverseCount == 0)
13365 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
13370 if(ReverseCount > 1)
13372 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
13373 NonRepeatingHeadCode);
13379 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
13381 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
13387 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
13389 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
13395 if(ForwardEntryPtr->LocationName ==
"")
13397 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
13398 ". One or other service does not have a location set");
13406 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
13407 ". One or other service does not have a location set");
13413 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
13415 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
13416 " is at a different location to the referencing train " + MainHeadCode);
13422 if(ForwardEntryPtr->Command ==
"F-nshs")
13425 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
13427 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
13428 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
13435 if(ForwardEntryPtr->Command ==
"Fns-sh")
13439 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
13441 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
13442 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
13449 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
13452 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13454 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
13455 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
13473 if(ForwardEntryPtr->Command ==
"Sns-sh")
13475 if(ReverseEntryPtr->
Command !=
"F-nshs")
13477 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
13478 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
13485 if(ForwardEntryPtr->Command ==
"F-nshs")
13487 if(ReverseEntryPtr->
Command !=
"Sns-sh")
13489 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
13490 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
13497 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13507 if(ForwardEntryPtr->Command ==
"Sns-fsh")
13509 if(ReverseEntryPtr->
Command !=
"Fns-sh")
13512 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
13513 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
13520 if(ForwardEntryPtr->Command ==
"Fns-sh")
13522 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
13525 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
13526 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
13533 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
13556 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
13557 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
13558 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
13559 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
13561 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
13585 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
13588 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
13589 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
13591 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
13593 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
13598 while(LastActionCommand ==
"Fns")
13600 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
13601 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
13602 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
13605 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
13606 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
13613 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
13616 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
13617 ". The linking of two or more shuttles is not permitted.");
13635 ShowMessage(Message);
13649 ShowMessage(Message);
13687 AnsiString(ActionEventType) +
"," + LocationID);
13688 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
13690 Prefix =
" ERROR: ";
13693 Prefix =
" HELD: ";
13694 ErrorLog =
" can't enter railway, train obstructing entry position ";
13695 WarningStr =
" can't enter railway, train obstructing entry position ";
13700 Prefix =
" HELD: ";
13701 ErrorLog =
" can't be created, train obstructing ";
13702 WarningStr =
" can't be created, train obstructing ";
13707 Prefix =
" HELD: ";
13708 ErrorLog =
" can't be created on a locked route at ";
13709 WarningStr =
" can't be created on a locked route at ";
13714 Prefix =
" HELD: ";
13715 ErrorLog =
" can't enter on a locked route at ";
13716 WarningStr =
" can't enter on a locked route at ";
13721 Prefix =
" HELD: ";
13722 ErrorLog =
" can't be created, diverging points at ";
13723 WarningStr =
" can't be created, diverging points at ";
13728 ErrorLog =
" left railway unexpectedly at ";
13733 ErrorLog =
" left railway at an incorrect exit at ";
13738 ErrorLog =
" failed to split - location too short at ";
13739 WarningStr =
" failed to split, location too short at ";
13744 Prefix =
" HELD: ";
13745 ErrorLog =
" unable to split - other train obstructing at ";
13746 WarningStr =
" unable to split - other train obstructing at ";
13750 ErrorLog =
" stopped at buffers unexpectedly at position ";
13753 ErrorLog =
" failed to stop at ";
13758 ErrorLog =
" failed to split at ";
13763 ErrorLog =
" failed to be joined by other train at ";
13768 ErrorLog =
" failed to join other train at ";
13773 ErrorLog =
" failed to terminate at ";
13778 ErrorLog =
" failed to form new service at ";
13783 ErrorLog =
" failed to exit railway ";
13788 ErrorLog =
" failed to change direction at ";
13793 ErrorLog =
" failed to pass ";
13797 ErrorLog =
" facing buffers and unable to start at ";
13800 ErrorLog =
" DERAILED at position ";
13801 Prefix =
" DERAILMENT: ";
13806 ErrorLog =
" CRASHED INTO BUFFERS at ";
13807 Prefix =
" CRASH: ";
13812 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
13813 Prefix =
" CRASH: ";
13818 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
13819 Prefix =
" CRASH: ";
13823 else if(ActionEventType ==
FailSPAD)
13825 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
13826 Prefix =
" SPAD: ";
13831 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
13832 Prefix =
" SPAD RISK: ";
13837 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
13841 Prefix =
" WARNING: ";
13842 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
13843 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
13848 Prefix =
" WARNING: ";
13849 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
13850 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
13889 std::ofstream OutFile(
"TrainData.csv");
13893 ShowMessage(
"Output file TrainData.csv failed to open");
13900 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
13905 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
13906 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
13907 "RepeatNumber" <<
'\n' <<
'\n';
13908 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13911 AnsiString TimetableEntryTypeStr;
13917 TimetableEntryTypeStr =
"NoFormat";
13923 TimetableEntryTypeStr =
"TimeLoc";
13929 TimetableEntryTypeStr =
"TimeTimeLoc";
13935 TimetableEntryTypeStr =
"TimeCmd";
13941 TimetableEntryTypeStr =
"StartNew";
13947 TimetableEntryTypeStr =
"TimeCmdHeadCode";
13953 TimetableEntryTypeStr =
"FinRemHere";
13959 TimetableEntryTypeStr =
"FNSShuttle";
13965 TimetableEntryTypeStr =
"SNTShuttle";
13971 TimetableEntryTypeStr =
"SNSShuttle";
13977 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
13983 TimetableEntryTypeStr =
"FSHNewService";
13989 TimetableEntryTypeStr =
"Repeat";
13995 TimetableEntryTypeStr =
"Default";
14005 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
14006 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
14009 AnsiString RunningEntryStr;
14015 RunningEntryStr =
"NotStarted";
14021 RunningEntryStr =
"Running";
14027 RunningEntryStr =
"Exited";
14030 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
14047 ShowMessage(Message);
14048 BaseTime = TDateTime::CurrentDateTime();
14062 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
14075 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
14078 for(
int x = 0; x < NumberOfTrains; x++)
14080 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
14100 int NumberOfTrains;
14107 for(
int x = 0; x < NumberOfTrains; x++)
14144 for(
int x = 0; x < LockedRouteVectorSize; x++)
14151 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
14162 int LockedRouteVectorSize;
14169 for(
int x = 0; x < LockedRouteVectorSize; x++)
14227 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
14235 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
14246 int ContinuationAutoSigVectorSize;
14253 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
14323 if(AVFirstEntry.
Command ==
"Snt")
14347 CTEMMP.second = CTEEntry;
14354 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
14362 CTEMMP.second = CTEEntry;
14383 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
14400 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
14402 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
14413 AnsiString RetStr =
"", PartStr =
"";
14528 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
14532 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
14534 AnsiString ShortTTName =
"";
14536 for(
int x = TTFileName.Length(); x > 0; x--)
14538 if(TTFileName[x] ==
'\\')
14540 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
14545 ShowMessage(
"Creates two timetables named " + ShortTTName +
14546 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
14548 Screen->Cursor = TCursor(-11);
14550 AnsiString FormatNoDPStr =
"#######0";
14551 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
14554 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
14561 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
14563 if(TrainDataEntry.
Mass > 0)
14564 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
14566 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
14568 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
14570 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
14571 FirstHeadCode = TrainDataEntry.
HeadCode;
14572 int IncDigits = 0, IncMinutes = 0;
14574 if(!ActionVector.empty())
14576 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
14578 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
14579 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
14588 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
14589 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
14594 for(
unsigned int z = 0; z < ActionVector.size(); z++)
14599 AnsiString PartStr =
"", TimeStr =
"";
14616 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
14620 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
14630 PartStr =
"Enters at " + LocName;
14643 PartStr =
"Created at " + LocName;
14657 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
14662 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
14667 else if(ActionVectorEntry.
Command ==
"Sfs")
14669 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
14673 else if(ActionVectorEntry.
Command ==
"Sns")
14675 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
14683 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
14689 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
14696 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
14699 AnsiString FirstHeadCode = TDE->
HeadCode;
14703 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
14715 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
14717 OneTTEntry.
Action = PartStr;
14718 OneTTEntry.
Time = TimeStr;
14720 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
14725 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
14731 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
14736 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
14744 else if(ActionVectorEntry.
Command ==
"jbo")
14746 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
14750 else if(ActionVectorEntry.
Command ==
"fsp")
14752 PartStr =
"Splits from front at " + ActionVectorEntry.
LocationName +
" to form";
14756 else if(ActionVectorEntry.
Command ==
"rsp")
14758 PartStr =
"Splits from rear at " + ActionVectorEntry.
LocationName +
" to form";
14762 else if(ActionVectorEntry.
Command ==
"cdt")
14764 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
14770 if(ActionVectorEntry.
Command ==
"Fns")
14772 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
14776 else if(ActionVectorEntry.
Command ==
"F-nshs")
14778 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
14784 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
14791 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
14797 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
14804 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
14809 else if(ActionVectorEntry.
Command ==
"Frh")
14811 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
14816 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
14820 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
14828 else if(ActionVectorEntry.
Command ==
"Fer")
14830 AnsiString AllowedExits;
14834 else if(ActionVectorEntry.
Command ==
"Fjo")
14836 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
14843 OneTTEntry.
Action = PartStr;
14844 OneTTEntry.
Time = TimeStr;
14851 AllTTTrains->push_back(OneTTLine);
14855 std::ofstream TTFile(TTFileName.c_str());
14859 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
14860 delete AllTTTrains;
14896 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
14897 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
14899 TTFile << AllTTTrains->at(x).Header.c_str();
14902 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
14904 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
14906 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
14910 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
14913 TTFile <<
'\n' <<
'\n';
14915 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
14917 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
14918 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
14920 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
14922 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
14926 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
14931 TTFile <<
'\n' <<
'\n';
14936 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
14938 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
14940 std::ofstream TTFile2(TTFileName2.c_str());
14944 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
14945 delete AllTTTrains;
14950 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
14951 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
14952 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
14954 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
14959 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
14960 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
14962 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
14964 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
14966 bool GiveMessagesFalse =
false;
14967 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
14968 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
14969 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
14973 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
14974 TimeString = TimeString.SubString(9, 5);
14975 ActionString +=
" " + OtherHeadCode;
14977 if(TimeString.SubString(1, 7) ==
"End at ")
14980 TimeString = TimeString.SubString(8, 5);
14982 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
14983 AnsiMultiMapEntry.first = TimeString;
14984 AnsiMultiMapEntry.second = OneLine;
14985 TAMM->insert(AnsiMultiMapEntry);
14990 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
14992 TTFile2 << (AMMIT->second).c_str();
14994 delete AllTTTrains;
15003 bool AtLocChecked,
int ArrRange,
int DepRange)
15007 bool AnalysisError =
false;
15031 TTrainDataVector::iterator TDVIt, TDVCopyIt;
15033 int IteratorNumber = 0;
15034 AnsiString AnsiSuffix =
"";
15039 for(TDVCopyIt = TrainDataVectorCopy.begin() + IteratorNumber; TDVCopyIt != TrainDataVectorCopy.end(); TDVCopyIt++)
15041 if(TDVCopyIt->ServiceReference == TDVIt->ServiceReference)
15044 AnsiSuffix = AnsiString(Suffix);
15045 TDVCopyIt->ServiceReference = TDVIt->ServiceReference +
"/" + AnsiSuffix;
15052 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
15053 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
15058 ServiceCallingLocsList.clear();
15059 if(ActionVector.empty())
15063 if(ActionVector.at(0).SignallerControl)
15067 for(
unsigned int z = 0; z < ActionVector.size(); z++)
15085 int HLoc = TE.
HLoc;
15086 int VLoc = TE.
VLoc;
15087 AnsiString HString;
15088 AnsiString VString;
15091 HString =
'N' + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
15095 HString = AnsiString(HLoc);
15099 VString =
'N' + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
15103 VString = AnsiString(VLoc);
15105 ServiceCallingLocsList.push_back(HString +
'-' + VString);
15128 else if(AVE.
Command ==
"cdt")
15130 if(ActionVector.at(z-1).SequenceType ==
Start)
15134 else if(ActionVector.at(z+1).SequenceType ==
Finish)
15141 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
15150 ServiceCallingLocsList.push_back(LName);
15154 int HLoc = TE.
HLoc;
15155 int VLoc = TE.
VLoc;
15156 AnsiString HString;
15157 AnsiString VString;
15160 HString =
'N' + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
15164 HString = AnsiString(HLoc);
15168 VString =
'N' + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
15172 VString = AnsiString(VLoc);
15174 ServiceCallingLocsList.push_back(HString +
'-' + VString);
15178 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
15212 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
15218 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
15219 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
15220 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
15224 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
15229 TDateTime LastTDTime;
15230 int IncMinutes = 0;
15232 if(ActionVector.empty())
15236 if(ActionVector.at(0).SignallerControl)
15240 if(AVLast->FormatType ==
Repeat)
15242 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
15250 if(AVLast->ArrivalTime != TDateTime(-1))
15252 LastTDTime = AVLast->ArrivalTime;
15254 else if(AVLast->EventTime != TDateTime(-1))
15256 LastTDTime = AVLast->EventTime;
15305 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
15310 int IncMinutes = 0;
15312 if(ActionVector.empty())
15316 if(ActionVector.at(0).SignallerControl)
15320 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
15322 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
15325 for(
int y = 0; y < NumTrains; y++)
15339 for(
unsigned int z = 0; z < ActionVector.size(); z++)
15354 LocServiceTimesVector.push_back(TLSTEntry);
15357 AnsiString IncTime =
"", FoundStopTime =
"";
15358 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
15360 if(ActionVector.at(a).FormatType ==
TimeLoc)
15365 if(ActionVector.at(a).SequenceType ==
Finish)
15371 if(FoundStopTime ==
"")
15373 throw Exception(
"Failure to determine FoundStopTime for located Snt");
15375 int WhileCount = 0;
15384 if(IncTime >= FoundStopTime)
15388 LocServiceTimesVector.push_back(TLSTEntry);
15389 if(WhileCount > 2000)
15391 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
15404 int HLoc = TE.
HLoc;
15405 int VLoc = TE.
VLoc;
15406 AnsiString HString;
15407 AnsiString VString;
15410 HString =
'N' + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
15414 HString = AnsiString(HLoc);
15418 VString =
'N' + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
15422 VString = AnsiString(VLoc);
15424 TLSTEntry.
Location = HString +
'-' + VString;
15428 LocServiceTimesVector.push_back(TLSTEntry);
15436 LocServiceTimesVector.push_back(TLSTEntry);
15438 AnsiString IncTime =
"", FoundStopTime =
"";
15439 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
15441 if(ActionVector.at(a).FormatType ==
TimeLoc)
15446 if(ActionVector.at(a).SequenceType ==
Finish)
15452 if(FoundStopTime ==
"")
15454 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
15456 int WhileCount = 0;
15465 if(IncTime >= FoundStopTime)
15469 LocServiceTimesVector.push_back(TLSTEntry);
15470 if(WhileCount > 2000)
15472 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
15482 bool SkipAddingMinutes =
false;
15485 LocServiceTimesVector.push_back(TLSTEntry);
15487 AnsiString IncTime =
"", FoundStopTime =
"";
15488 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
15490 if(ActionVector.at(a).FormatType ==
TimeLoc)
15495 if(ActionVector.at(a).SequenceType ==
Finish)
15498 if((a == z + 1) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr > 0) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr > 0)))
15501 LocServiceTimesVector.pop_back();
15502 SkipAddingMinutes =
true;
15507 if(FoundStopTime ==
"")
15509 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
15511 if(!SkipAddingMinutes)
15513 int WhileCount = 0;
15522 if(IncTime >= FoundStopTime)
15526 LocServiceTimesVector.push_back(TLSTEntry);
15527 if(WhileCount > 2000)
15529 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
15538 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
15540 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
15542 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
15543 LocServiceTimesVector.pop_back();
15544 LocServiceTimesVector.push_back(TLSTEntry);
15549 LocServiceTimesVector.push_back(TLSTEntry);
15555 LocServiceTimesVector.push_back(TLSTEntry);
15574 LocServiceTimesVector.push_back(TLSTEntry);
15578 AnsiString TempDepTime = TLSTEntry.
DepTime;
15580 LocServiceTimesVector.push_back(TLSTEntry);
15582 while(TLSTEntry.
AtLocTime < TempDepTime)
15587 TLSTEntry.
DepTime = TempDepTime;
15588 LocServiceTimesVector.push_back(TLSTEntry);
15592 LocServiceTimesVector.push_back(TLSTEntry);
15610 AnsiString HString;
15611 AnsiString VString;
15614 HString =
'N' + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
15618 HString = AnsiString(HLoc);
15622 VString =
'N' + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
15626 VString = AnsiString(VLoc);
15628 TLSTEntry.
Location = HString +
'-' + VString;
15630 LocServiceTimesVector.push_back(TLSTEntry);
15635 AnsiString FrhTime;
15636 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
15640 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
15648 LocServiceTimesVector.push_back(TLSTEntry);
15654 LocServiceTimesVector.push_back(TLSTEntry);
15659 else if(AVE.
Command ==
"Frh-sh")
15661 if(y == NumTrains - 1)
15667 LocServiceTimesVector.push_back(TLSTEntry);
15673 LocServiceTimesVector.push_back(TLSTEntry);
15692 TLocServiceTimesVector::iterator Ptr1, Ptr2;
15695 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
15696 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
15698 std::ofstream TTFile3(TTFileName3.c_str());
15702 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
15707 if(LocServiceTimesVector.empty())
15709 ShowMessage(
"No timetabled services found");
15711 DeleteFile(TTFileName3);
15716 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n\n\n";
15723 Ptr1 = LocServiceTimesVector.begin();
15725 while(Ptr2 != LocServiceTimesVector.end())
15727 while(Ptr2->Location == Ptr1->Location)
15730 if(Ptr2 == LocServiceTimesVector.end())
15737 if(Ptr2 != LocServiceTimesVector.end())
15745 TTFile3 <<
"Arrival analysis: an asterisk means that the number of same approach code arrivals is equal to or greater than the number of platforms.\n";
15746 TTFile3 <<
"If the total number of arrivals exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
15747 MinuteString =
" minutes";
15748 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
15751 MinuteString =
" minute";
15753 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
15754 TTFile3 <<
",Platforms,Trains\n\n";
15756 Ptr1 = LocServiceTimesVector.begin();
15758 while(Ptr2 != LocServiceTimesVector.end())
15760 PreviousService =
"";
15761 NumTrainsAtLoc = 0;
15762 ServiceAndRepeatNumTotal =
"";
15764 NumPlatsAtThisLocCalculated =
false;
15766 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
15768 PreviousService =
"";
15769 NumTrainsAtLoc = 0;
15770 ServiceAndRepeatNumTotal =
"";
15772 NumPlatsAtThisLocCalculated =
false;
15776 if(Ptr2 == LocServiceTimesVector.end())
15781 if(Ptr2 == LocServiceTimesVector.end())
15785 while(Ptr2->Location == Ptr1->Location)
15787 PreviousService =
"";
15788 NumTrainsAtLoc = 0;
15789 ServiceAndRepeatNumTotal =
"";
15790 BasicTime = Ptr1->ArrTime;
15791 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
15795 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
15797 BasicTime = Ptr2->ArrTime;
15800 if(Ptr2 == LocServiceTimesVector.end())
15804 if(Ptr2->Location != Ptr1->Location)
15809 if(Ptr2 == LocServiceTimesVector.end())
15813 if(Ptr2->Location != Ptr1->Location)
15819 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
15823 if(!NumPlatsAtThisLocCalculated)
15826 NumPlatsAtThisLocCalculated =
true;
15828 if(Ptr1->ServiceAndRepeatNum != PreviousService)
15830 if(ServiceAndRepeatNumTotal ==
"")
15832 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
15833 NumTrainsAtLoc = 1;
15837 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
15840 PreviousService = Ptr2->ServiceAndRepeatNum;
15841 if(ServiceAndRepeatNumTotal ==
"")
15843 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
15844 NumTrainsAtLoc = 1;
15848 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
15852 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
15854 int MaxNumberOfSameDirections = 0;
15855 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
15860 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
15864 AnsiString Asterisk =
"";
15865 if(MaxNumberOfSameDirections >= NumPlats)
15870 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
15871 ArrivalsPrinted =
true;
15872 ServiceAndRepeatNumTotal =
"";
15874 if(Ptr2 == LocServiceTimesVector.end())
15878 if(Ptr2->Location != Ptr1->Location)
15883 if(Ptr2 == LocServiceTimesVector.end())
15889 if(!ArrivalsPrinted)
15891 TTFile3 <<
"Nothing to report for arrivals";
15893 TTFile3 <<
"\n\n\n";
15901 Ptr1 = LocServiceTimesVector.begin();
15903 while(Ptr2 != LocServiceTimesVector.end())
15905 while(Ptr2->Location == Ptr1->Location)
15908 if(Ptr2 == LocServiceTimesVector.end())
15915 if(Ptr2 != LocServiceTimesVector.end())
15922 TTFile3 <<
"Departure analysis: an asterisk means that the number of same exit code departures is equal to or greater than the number of platforms.\n";
15923 TTFile3 <<
"If the total number of departures exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
15924 MinuteString =
" minutes";
15925 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
15928 MinuteString =
" minute";
15930 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
15931 TTFile3 <<
",Platforms,Trains\n\n";
15933 Ptr1 = LocServiceTimesVector.begin();
15935 while(Ptr2 != LocServiceTimesVector.end())
15937 PreviousService =
"";
15938 NumTrainsAtLoc = 0;
15939 ServiceAndRepeatNumTotal =
"";
15941 NumPlatsAtThisLocCalculated =
false;
15943 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
15945 PreviousService =
"";
15946 NumTrainsAtLoc = 0;
15947 ServiceAndRepeatNumTotal =
"";
15949 NumPlatsAtThisLocCalculated =
false;
15953 if(Ptr2 == LocServiceTimesVector.end())
15958 if(Ptr2 == LocServiceTimesVector.end())
15962 while(Ptr2->Location == Ptr1->Location)
15964 PreviousService =
"";
15965 NumTrainsAtLoc = 0;
15966 ServiceAndRepeatNumTotal =
"";
15967 BasicTime = Ptr1->DepTime;
15968 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
15972 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
15974 BasicTime = Ptr2->DepTime;
15977 if(Ptr2 == LocServiceTimesVector.end())
15981 if(Ptr2->Location != Ptr1->Location)
15986 if(Ptr2 == LocServiceTimesVector.end())
15990 if(Ptr2->Location != Ptr1->Location)
15996 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
16000 if(!NumPlatsAtThisLocCalculated)
16003 NumPlatsAtThisLocCalculated =
true;
16005 if(Ptr1->ServiceAndRepeatNum != PreviousService)
16007 if(ServiceAndRepeatNumTotal ==
"")
16009 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
16010 NumTrainsAtLoc = 1;
16014 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
16017 PreviousService = Ptr2->ServiceAndRepeatNum;
16018 if(ServiceAndRepeatNumTotal ==
"")
16020 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
16021 NumTrainsAtLoc = 1;
16025 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
16029 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
16031 int MaxNumberOfSameDirections = 0;
16032 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
16037 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
16041 AnsiString Asterisk =
"";
16042 if(MaxNumberOfSameDirections >= NumPlats)
16047 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
16048 DeparturesPrinted =
true;
16049 ServiceAndRepeatNumTotal =
"";
16051 if(Ptr2 == LocServiceTimesVector.end())
16055 if(Ptr2->Location != Ptr1->Location)
16060 if(Ptr2 == LocServiceTimesVector.end())
16066 if(!DeparturesPrinted)
16068 TTFile3 <<
"Nothing to report for departures";
16070 TTFile3 <<
"\n\n\n";
16080 Ptr1 = LocServiceTimesVector.begin();
16082 while(Ptr2 != LocServiceTimesVector.end())
16084 while(Ptr2->Location == Ptr1->Location)
16087 if(Ptr2 == LocServiceTimesVector.end())
16094 if(Ptr2 != LocServiceTimesVector.end())
16101 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
16102 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
16103 TTFile3 <<
",Platforms,Trains,\n\n";
16104 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
16105 Ptr1 = LocServiceTimesVector.begin();
16107 while(Ptr2 != LocServiceTimesVector.end())
16109 PreviousService =
"";
16110 ServiceAndRepeatNumTotal =
"";
16111 NumTrainsAtLoc = 0;
16113 NumPlatsAtThisLocCalculated =
false;
16115 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
16117 PreviousService =
"";
16118 ServiceAndRepeatNumTotal =
"";
16119 NumTrainsAtLoc = 0;
16121 NumPlatsAtThisLocCalculated =
false;
16125 if(Ptr2 == LocServiceTimesVector.end())
16130 if(Ptr2 == LocServiceTimesVector.end())
16134 while(Ptr2->Location == Ptr1->Location)
16136 if(Ptr1->FrhMarker ==
"Frh")
16139 Ptr1->FrhMarker =
"FrhCounted";
16141 PreviousService =
"";
16142 NumTrainsAtLoc = 0;
16143 ServiceAndRepeatNumTotal =
"";
16144 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
16148 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
16151 if(Ptr1->FrhMarker ==
"Frh")
16154 Ptr1->FrhMarker =
"FrhCounted";
16157 if(Ptr2 == LocServiceTimesVector.end())
16161 if(Ptr2->Location != Ptr1->Location)
16166 if(Ptr2 == LocServiceTimesVector.end())
16170 if(Ptr2->Location != Ptr1->Location)
16174 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
16176 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
16180 if(!NumPlatsAtThisLocCalculated)
16183 NumPlatsAtThisLocCalculated =
true;
16185 if(Ptr1->ServiceAndRepeatNum != PreviousService)
16187 if(ServiceAndRepeatNumTotal ==
"")
16189 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
16190 NumTrainsAtLoc = 1;
16194 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
16197 PreviousService = Ptr2->ServiceAndRepeatNum;
16198 if(ServiceAndRepeatNumTotal ==
"")
16200 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
16201 NumTrainsAtLoc = 1;
16205 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
16208 if(Ptr1->FrhMarker ==
"Frh")
16211 Ptr1->FrhMarker =
"FrhCounted";
16214 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
16218 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
16220 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
16222 AnsiString Asterisk =
"";
16223 if(NumTrainsAtLoc > NumPlats)
16230 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
16232 else if(FrhCount == 1)
16234 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
16238 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
16240 LastFrhCount = FrhCount;
16241 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
16242 AtLocsPrinted =
true;
16243 ServiceAndRepeatNumTotal =
"";
16246 if(Ptr2 == LocServiceTimesVector.end())
16250 if(Ptr2->Location != Ptr1->Location)
16255 if(Ptr2 == LocServiceTimesVector.end())
16263 TTFile3 <<
"Nothing to report for trains at locations";
16265 TTFile3 <<
"\n\n\n";
16287 catch(
const Exception &e)
16289 AnsiString TTErrorFileName =
"Analysis Error.txt";
16290 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
16291 std::ofstream TTError(TTErrorFileName.c_str());
16294 ShowMessage(
"Analysis error file failed to open - can't be created");
16298 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16299 TTError << TimeNow.c_str() <<
"\n" << ArrRange <<
"\n" << ArrChecked <<
"\n" << DepRange <<
"\n" <<
16300 DepChecked <<
"\n" << AtLocChecked <<
"\n" << AnsiString(e.Message);
16302 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
16314 if((Time1 ==
"") || (Time2 ==
""))
16319 int Mins = Time1.SubString(4,2).ToInt();
16320 int Hours = Time1.SubString(1,2).ToInt();
16321 int Time1Mins = (Hours * 60) + Mins;
16322 Mins = Time2.SubString(4,2).ToInt();
16323 Hours = Time2.SubString(1,2).ToInt();
16324 int Time2Mins = (Hours * 60) + Mins;
16325 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
16337 bool &AnalysisError,
int &MaxNumberOfSameDirections)
16343 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
16345 std::list<AnsiString> ServiceList;
16347 bool EvenComma =
false;
16348 for(
int x = 1; x <= Input.Length(); x++)
16350 TempStr1 = Input[x];
16351 if(TempStr1 == AnsiString(
',') && EvenComma)
16357 TempStr2 += Input[x];
16359 if(TempStr1 == AnsiString(
','))
16361 EvenComma = !EvenComma;
16365 while(TempStr2.Length() > 0)
16367 SCPos = TempStr2.Pos(
';');
16370 OneService = TempStr2.SubString(1, SCPos - 1);
16371 ServiceList.push_back(OneService);
16372 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
16376 ServiceList.push_back(TempStr2);
16380 ServiceList.sort();
16381 ServiceList.unique();
16382 NumTrainsAtLoc = ServiceList.size();
16385 int DirectionMarker = 0;
16387 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
16389 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
16391 *SLIt = *SLIt +
"&0";
16393 SLIt3 = ServiceList.end();
16395 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
16396 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
16397 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
16399 MaxNumberOfSameDirections = 0;
16400 int SameDirectionCount = 0;
16402 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
16406 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
16412 CommaPos1 = SLIt1->Pos(
',');
16413 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
16415 SpacePos = ServiceRef1.Pos(
' ');
16419 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
16420 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
16421 if(RepeatInfo1[1] ==
'F')
16427 SpacePos = RepeatInfo1.Pos(
' ');
16428 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
16431 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
16433 AmpersandPos = AnsiTime1.Pos(
'&');
16434 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
16439 throw Exception(
"ASCLIt1 Error in " + Input);
16441 ServiceCallingLocsList1 = ASCLIt1->second;
16442 AmpersandPos = SLIt1->Pos(
'&');
16443 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
16444 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
16446 SameDirectionCount = 1;
16447 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
16449 CommaPos2 = SLIt2->Pos(
',');
16450 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
16452 SpacePos = ServiceRef2.Pos(
' ');
16456 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
16457 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
16458 if(RepeatInfo2[1] ==
'F')
16464 SpacePos = RepeatInfo2.Pos(
' ');
16465 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
16469 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
16471 AmpersandPos = AnsiTime2.Pos(
'&');
16472 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
16477 throw Exception(
"ASCLIt2 Error in " + Input);
16479 ServiceCallingLocsList2 = ASCLIt2->second;
16481 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
16483 int AmpersandPos = SLIt2->Pos(
'&');
16484 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
16485 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
16486 SameDirectionCount++;
16489 if(SameDirectionCount > MaxNumberOfSameDirections)
16491 MaxNumberOfSameDirections = SameDirectionCount;
16496 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
16498 AmpersandPos = SLIt3->Pos(
'&');
16499 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
16500 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
16504 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
16507 AmpersandPos = SLIt->Pos(
'&');
16508 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
16509 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
16510 DirectionMarker = DirectionMarkerString.ToInt();
16511 AnsiString DirectionSuffix =
"";
16513 if(DirectionMarker < 27)
16515 c = 64 + DirectionMarker;
16516 DirectionSuffix =
"," + AnsiString(c);
16518 else if(DirectionMarker < 53)
16520 c = 65 + DirectionMarker - 27;
16521 DirectionSuffix =
",A" + AnsiString(c);
16525 DirectionSuffix =
",?";
16527 *SLIt = ServiceWithoutMarker + DirectionSuffix;
16530 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
16532 Output = Output + *SLIt +
",";
16534 if(Output.Length() > 0)
16536 Output = Output.SubString(1, Output.Length() - 1);
16542 catch(
const Exception &e)
16544 AnalysisError =
true;
16555 AnsiString InternalInput = Input, Output =
"", OneService =
"";
16557 std::list<AnsiString> ServiceList;
16559 while(InternalInput.Length() > 0)
16561 CommaPos = InternalInput.Pos(
',');
16564 OneService = InternalInput.SubString(1, CommaPos - 1);
16565 ServiceList.push_back(OneService);
16566 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
16570 ServiceList.push_back(InternalInput);
16571 InternalInput =
"";
16575 ServiceList.sort();
16576 ServiceList.unique();
16577 NumTrainsAtLoc = ServiceList.size();
16578 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
16580 Output = Output + *SLIt +
",";
16582 if(Output.Length() > 0)
16584 Output = Output.SubString(1, Output.Length() - 1);
16597 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
16599 std::list<AnsiString>::iterator LP1 = 0, LP2 = 0, ListPtr1 = 0, ListPtr2 = 0, LocPtr1 = 0, LocPtr2 = 0;
16604 bool LocFound =
false;
16605 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
16607 TDateTime FirstServiceTime;
16610 int Ref1Target = 0, Ref1Count = 0;
16611 int SlashPos = Ref1.Pos(
'/');
16614 Ref1Target = Ref1.SubString(SlashPos + 1, Ref1.Length() - SlashPos).ToInt();
16615 Ref1 = Ref1.SubString(1, SlashPos - 1);
16617 int Ref2Target = 0, Ref2Count = 0;
16618 SlashPos = Ref2.Pos(
'/');
16621 Ref2Target = Ref2.SubString(SlashPos + 1, Ref2.Length() - SlashPos).ToInt();
16622 Ref2 = Ref2.SubString(1, SlashPos - 1);
16625 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
16627 if((*ListPtr1) == Location)
16629 LocPtr1 = ListPtr1;
16632 if(ListPtr1->SubString(1, 3) ==
"%%%")
16634 AnsiString CDTTime = ListPtr1->SubString(4, 5);
16639 FirstServiceTime = TDateTime(-1);
16640 bool BreakFlag =
false;
16643 if(TDVIt->ServiceReference == Ref1)
16645 if(Ref1Target > Ref1Count)
16650 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
16651 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
16655 FirstServiceTime = AVIt->EventTime;
16661 FirstServiceTime = AVIt->ArrivalTime;
16667 FirstServiceTime = AVIt->DepartureTime;
16678 if(IncMinutes == -1)
16680 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
16682 if(FirstServiceTime == TDateTime(-1))
16684 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
16688 if(!Arrival && (Time1 == CDTTime))
16693 if(Arrival && (Time1 == CDTTime))
16697 if(Time1 > CDTTime)
16702 if(Time1 < CDTTime)
16716 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
16718 if((*ListPtr2) == Location)
16720 LocPtr2 = ListPtr2;
16723 if(ListPtr2->SubString(1, 3) ==
"%%%")
16725 AnsiString CDTTime = ListPtr2->SubString(4, 5);
16730 FirstServiceTime = TDateTime(-1);
16731 bool BreakFlag =
false;
16734 if(TDVIt->ServiceReference == Ref2)
16736 if(Ref2Target > Ref2Count)
16741 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
16742 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
16746 FirstServiceTime = AVIt->EventTime;
16752 FirstServiceTime = AVIt->ArrivalTime;
16758 FirstServiceTime = AVIt->DepartureTime;
16769 if(IncMinutes == -1)
16771 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
16773 if(FirstServiceTime == TDateTime(-1))
16775 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
16779 if(!Arrival && (Time2 == CDTTime))
16784 if(Arrival && (Time2 == CDTTime))
16788 if(Time2 > CDTTime)
16793 if(Time2 < CDTTime)
16809 LP1 = List1.begin();
16811 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
16813 if(ListPtr1 == List1.begin())
16817 if(ListPtr1->SubString(1, 3) ==
"%%%")
16824 LP2 = List2.begin();
16826 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
16828 if(ListPtr2 == List2.begin())
16832 if(ListPtr2->SubString(1, 3) ==
"%%%")
16842 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
16844 if(ListPtr1 == LocPtr1)
16848 if(ListPtr1->SubString(1, 3) ==
"%%%")
16852 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
16854 if(ListPtr2 == LocPtr2)
16858 if(ListPtr2->SubString(1, 3) ==
"%%%")
16862 if((*ListPtr1) == (*ListPtr2))
16875 LP1 = LocPtr1; LP1++;
16876 LP2 = LocPtr2; LP2++;
16877 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
16879 if(ListPtr1 == List1.end())
16883 if(ListPtr1->SubString(1, 3) ==
"%%%")
16887 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
16889 if(ListPtr2 == List2.end())
16893 if(ListPtr2->SubString(1, 3) ==
"%%%")
16897 if((*ListPtr1) == (*ListPtr2))
16914 if(ExitList.empty())
16919 AnsiString ExitLocList =
"";
16922 unsigned int Counter = 0;
16927 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
16929 ExitLocList +=
"\n";
16932 if(StartName ==
"")
16934 if(ExitList.size() == 1)
16938 return " at " + ID;
16943 if(ExitList.size() < 4)
16945 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
16950 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
16960 if(ExitList.size() < 4)
16962 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
16967 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
16973 if(ExitList.size() < 4)
16975 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
16976 return " at " + StartName;
16980 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
16981 return " at " + StartName;
17021 AnsiString FormatStr =
"####0.0";
17022 AnsiString AvLateArrMins =
"";
17023 AnsiString AvEarlyArrMins =
"";
17024 AnsiString AvLatePassMins =
"";
17025 AnsiString AvEarlyPassMins =
"";
17026 AnsiString AvLateDepMins =
"";
17039 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
17040 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
17048 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
17050 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
17055 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
17057 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
17062 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
17067 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
17069 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
17071 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
17074 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
17076 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
17078 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
17081 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
17083 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
17086 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
17088 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
17090 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
17092 TDateTime TempExcessLCDownTime;
17103 if(TempExcessLCDownTime > TDateTime(0))
17109 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
17112 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
17115 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
17117 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
17135 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
17137 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
17143 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
17147 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
17151 AnsiString AvLateMinsLocsNotReached =
"";
17157 if(LocsNotReached > 0)
17160 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
17164 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
17166 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
17174 PerfFile <<
Derailments <<
" derailments" <<
'\n';
17176 PerfFile <<
Derailments <<
" derailment" <<
'\n';
17183 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
17185 bool DerailSPADFlag =
false, CrashFlag =
false;
17187 int OverallScorePercent = 100;
17189 double TotLateMinsFactor = 1;
17190 double MissedStopAndSPADRiskFactor = 1;
17191 double NetNegFactor = 1;
17200 OverallScorePercent = 5;
17201 DerailSPADFlag =
true;
17205 OverallScorePercent = 0;
17208 if(OverallScorePercent == 100)
17212 TotLateMinsFactor =
17220 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
17222 OverallScorePercent = 100 * NetNegFactor;
17225 if((TotArrDep > 0) || DerailSPADFlag || CrashFlag)
17228 AnsiString OneFailureString =
", though the failure would account for some poor performance";
17229 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
17230 AnsiString AddedString =
"";
17232 AddedString = OneFailureString;
17234 AddedString = TwoOrMoreFailureString;
17235 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
17236 AnsiString Rating =
"";
17237 if(OverallScorePercent == 100)
17238 Rating =
"Perfect!";
17239 else if(OverallScorePercent >= 95)
17240 Rating =
"Excellent";
17241 else if(OverallScorePercent >= 90)
17242 Rating =
"Very good";
17243 else if(OverallScorePercent >= 80)
17245 else if(OverallScorePercent >= 70)
17247 else if(OverallScorePercent >= 60)
17248 Rating =
"Unacceptable" + AddedString;
17249 else if(OverallScorePercent >= 50)
17250 Rating =
"Poor" + AddedString;
17251 else if(OverallScorePercent >= 40)
17252 Rating =
"Bad" + AddedString;
17253 else if(OverallScorePercent >= 30)
17254 Rating =
"Very bad" + AddedString;
17255 else if(OverallScorePercent >= 20)
17256 Rating =
"Terrible" + AddedString;
17257 else if(OverallScorePercent >= 10)
17258 Rating =
"Appalling" + AddedString;
17259 else if(OverallScorePercent >= 5)
17262 Rating =
"Disastrous - potential loss of life";
17265 Rating =
"Dire" + AddedString;
17267 else if(OverallScorePercent < 5)
17270 Rating =
"Catastrophic - loss of life";
17272 Rating =
"Abysmal";
17274 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
17278 PerfFile <<
"\nThere were no timetabled departures or arrivals so there is insufficient information to provide a performance score or rating" <<
'\n';
17280 PerfFile <<
'\n' <<
"***************************************";
17289 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17339 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17371 int IncrementalMinutes = 0;
17383 bool TrainOperatingFlag =
false;
17388 TrainOperatingFlag =
true;
17392 if(TrainOperatingFlag)
17399 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
17444 AnsiString HeadCode;
17448 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17452 HCandTrainPosParam.first = HeadCode;
17453 HCandTrainPosParam.second = TrainID;
17455 if((TimeToAct >= 0) && (TimeToAct < 59.9))
17458 OpTimeToActMultiMapEntry.first = TimeToAct;
17459 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
17489 float TimeToAct = 0;
17490 int DistanceToRedSignal = 0;
17493 ContinuationEntryVecPosVector.clear();
17494 bool LaterTrain =
false;
17498 LaterTrain =
false;
17499 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
17510 if(!ContinuationEntryVecPosVector.empty())
17512 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
17514 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
17516 LaterTrain =
true; ;
17527 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
17528 AnsiString HeadCode = CTEIt->second.HeadCode;
17529 float CurrentStopTime;
17530 float LaterStopTime;
17531 float RecoverableTime;
17534 bool SigControlAndCanPassRedSignal =
false;
17538 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(1),
17540 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed);
17543 if(AvTrackSpeed < 30)
17545 if(DistanceToRedSignal == -1)
17551 int Speed = AvTrackSpeed;
17552 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
17553 if(AvTrackSpeed > MaxSpeed)
17555 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(1).SignallerControl)
17558 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
17561 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
17566 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
17567 TimeToAct += MinsBefEnter;
17570 HCandTrainPosParam.first = HeadCode;
17571 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
17574 if(TimeToAct < 59.9)
17576 OpTimeToActMultiMapEntry.first = TimeToAct;
17577 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
17589 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
17590 float &RecoverableTime,
int &AvTrackSpeed)
17599 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
17600 int DistanceToRedSignal = 0;
17601 int CumTrackSpeed = 0;
17603 int TrackSpeedCount = 0;
17614 int CurrentElement = TrackVectorPosition;
17615 int CurrentEntryPos = TrackVectorPositionEntryPos;
17620 CurrentStopTime = 0;
17622 RecoverableTime = 0;
17623 if(CurrentElement == -1)
17628 int CurrentExitPos;
17633 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
17636 CurrentExitPos = 1;
17638 CurrentExitPos = 3;
17641 CurrentExitPos = 0;
17674 CurrentStopTime = float(TimeToDepart);
17681 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
17692 else if(SigControlAndCanPassRedSignal)
17697 if((NextEntryPos == 0) || (NextEntryPos == 2))
17711 CurrentElement = NextElement;
17712 CurrentEntryPos = NextEntryPos;
17713 CurrentExitPos = NextExitPos;
17725 int LaterStopNumber = 0;
17729 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
17738 if(CurrentEntryPos > 1)
17758 bool StopRequired =
false;
17776 int TrainOnElement;
17783 if(CurrentEntryPos > 1)
17788 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
17798 double StopTimeDouble;
17809 if(StopTimeDouble < 0.5)
17810 StopTimeDouble = 0.5;
17813 LaterStopTime += float(StopTimeDouble);
17814 RecoverableTime += StopTimeDouble - 0.5;
17815 if((LaterStopNumber == 1) && (TrainID > -1))
17821 if((AVPtr + 1)->FormatType ==
TimeLoc)
17825 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
17827 if(StopTimeDouble < 0.5)
17828 StopTimeDouble = 0.5;
17830 LaterStopTime += float(StopTimeDouble);
17831 RecoverableTime += StopTimeDouble - 0.5;
17832 if((LaterStopNumber == 1) && (TrainID > -1))
17847 if(NextElement == -1)
17856 if((NextEntryPos == 0) || (NextEntryPos == 2))
17870 CurrentElement = NextElement;
17871 CurrentEntryPos = NextEntryPos;
17872 CurrentExitPos = NextExitPos;
17876 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
17891 float MaxAllowableSpeed;
17893 if(TrackSpeedCount > 0)
17894 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
17897 if(CurrentEntryPos > 1)
17907 float KmPerLocationStop;
17909 if(LaterStopNumber > 0)
17911 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
17912 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
17916 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
17920 if(AvTrackSpeed > MaxAllowableSpeed)
17921 AvTrackSpeed = MaxAllowableSpeed;
17923 return DistanceToRedSignal;